package com.ruoyi.standingbook.v2toilet.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.tools.constant.ERecordConstant;
import com.ruoyi.common.tools.excel.MyExcelUtil;
import com.ruoyi.common.tools.excel.base.MyExcelResult;
import com.ruoyi.common.tools.excel.listener.V2ToiletExcelListener;
import com.ruoyi.common.tools.utils.SerialGenerator;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.standingbook.v2toilet.ItemEnum;
import com.ruoyi.standingbook.v2toilet.ToiletConst;
import com.ruoyi.standingbook.v2toilet.domain.V2ToiletImpBase;
import com.ruoyi.standingbook.v2toilet.domain.bo.V2ToiletBillBo;
import com.ruoyi.standingbook.v2toilet.domain.bo.V2ToiletImpBaseBo;
import com.ruoyi.standingbook.v2toilet.domain.vo.V2ToiletImpBaseVo;
import com.ruoyi.standingbook.v2toilet.domain.vo.V2ToiletImpDetailVo;
import com.ruoyi.standingbook.v2toilet.enums.ItemStatusEnum;
import com.ruoyi.standingbook.v2toilet.logic.V2ExtendAsyncService;
import com.ruoyi.standingbook.v2toilet.logic.V2ExtendProcessService;
import com.ruoyi.standingbook.v2toilet.mapper.V2ToiletImpBaseMapper;
import com.ruoyi.standingbook.v2toilet.service.IToiletImpBaseService;
import com.ruoyi.system.domain.vo.SysOssVo;
import com.ruoyi.system.service.ISysOssService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * V2市政公厕管养导入Service业务层处理
 *
 * @author cc
 * @date 2023-06-07
 */
@RequiredArgsConstructor
@Service
public class V2ToiletImpBaseServiceImpl implements IToiletImpBaseService {
    private final ISysOssService iSysOssService;
    private final V2ToiletImpBaseMapper baseMapper;
    private final V2ExtendProcessService v2ToiletExcelService;
    private final V2ExtendAsyncService asyncService;
    //erecord:    api:    call: false
    @Value("${erecord.api.call:true}")
    private boolean callApi;


    /**
     * 查询V2市政公厕管养导入
     */
    @Override
    public V2ToiletImpBaseVo queryById(String batchNo) {
        return baseMapper.selectVoById(batchNo);
    }

    /**
     * 查询V2市政公厕管养导入列表
     */
    @Override
    public TableDataInfo<V2ToiletImpBaseVo> queryPageList(V2ToiletImpBaseBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<V2ToiletImpBase> lqw = buildQueryWrapper(bo);
        Page<V2ToiletImpBaseVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);

        return TableDataInfo.build(result);
    }

    /**
     * 查询V2市政公厕管养导入列表
     */
    @Override
    public List<V2ToiletImpBaseVo> queryList(V2ToiletImpBaseBo bo) {
        LambdaQueryWrapper<V2ToiletImpBase> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<V2ToiletImpBase> buildQueryWrapper(V2ToiletImpBaseBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<V2ToiletImpBase> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getBatchNo()), V2ToiletImpBase::getBatchNo, bo.getBatchNo());
        lqw.eq(bo.getProcessStatus() != null, V2ToiletImpBase::getProcessStatus, bo.getProcessStatus());
        lqw.eq(bo.getAttachMsg() != null, V2ToiletImpBase::getAttachMsg, bo.getAttachMsg());
        lqw.eq(bo.getCreateTime() != null, V2ToiletImpBase::getCreateTime, bo.getCreateTime());
        lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null, V2ToiletImpBase::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime"));
        lqw.orderByDesc(V2ToiletImpBase::getCreateTime);
        return lqw;
    }

    /**
     * 新增V2市政公厕管养导入
     */
    @Override
    public Boolean insertByBo(V2ToiletImpBaseBo bo) {
        V2ToiletImpBase add = BeanUtil.toBean(bo, V2ToiletImpBase.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setBatchNo(add.getBatchNo());
        }
        return flag;
    }

    /**
     * 修改V2市政公厕管养导入
     */
    @Override
    public Boolean updateByBo(V2ToiletImpBaseBo bo) {
        V2ToiletImpBase update = BeanUtil.toBean(bo, V2ToiletImpBase.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(V2ToiletImpBase entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除V2市政公厕管养导入
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        //        return baseMapper.deleteBatchIds(ids) > 0;
        return baseMapper.realDelByIds(ids) > 0;
    }

    @Override
    public R<Void> importExcel(V2ToiletImpBaseBo bo) {
        // 生成批次号
        final String batchNo = SerialGenerator.generator.nextId();
        bo.setBatchNo(batchNo);
        // excel 处理
        MyExcelResult<V2ToiletImpDetailVo> excelResult = MyExcelUtil.getImportExcelData(
            bo.getExcelUrl(),
            bo.getExcelUrl(),
            new V2ToiletExcelListener(batchNo),
            V2ToiletImpDetailVo.class,
            true
        );

        if (null == excelResult) {
            return R.fail("Excel转换数据对象失败");
        }
        // 更新主表状态
        if (excelResult.isSuccess()) {
            bo.setProcessStatus(ERecordConstant.COMMON_STATUS_SUCCESS);
        } else {
            bo.setProcessStatus(ERecordConstant.COMMON_STATUS_ERROR);
        }
        bo.setProcessMsg(excelResult.getAnalysis());
        bo.setAttachMsg(ERecordConstant.ATTACH_UPLOAD_STATUS_NO);

        //去掉没有设置ID的
        List<V2ToiletImpDetailVo> collect = excelResult.getList().stream()
            .filter(e -> Objects.nonNull(e.getId())).collect(Collectors.toList());

        String checked = checkData(collect);
        if(!StringUtils.isEmpty(checked)){
            return R.fail("Excel管养"+checked+"异常数据无拍照");
        }

        Map<String, Object> query = new HashMap<>();
        //用管养日期和 是否已经改变选项来确定
        query.put(ToiletConst.MODIFY_KEY, ToiletConst.MODIFY_NOT);

        List<V2ToiletBillBo> bills = new ArrayList<>();//异常工单
        //填充数据
        collect.forEach(detail -> fitBillData(detail, bills, query));
        //填充数据 END
        bo.setProcessMsg(getAnalysis(excelResult));
        if (insertByBo(bo)) {
            v2ToiletExcelService.saveExcelData(collect, bills, query);
            //            @Value("${erecord.api.call:true}")
            //            private boolean callApi;
            if (callApi) {
                asyncService.sendBills();
            }

        } else {
            return R.fail("导入数据对象失败");
        }
        return R.ok();
    }

    /**
     * 数据转换 填充订单数据
     *
     * @param data  厕所导入集合
     * @param bills 工单集合
     * @param query 待发送数据
     */
    private void fitBillData(V2ToiletImpDetailVo data, List<V2ToiletBillBo> bills, Map<String, Object> query) {
        query.put(ToiletConst.QUERY_INSPECT_DATE, DateUtil.format(data.getCreateDate(), "yyyy-MM-dd"));
        JSONObject jsonObject = JSONUtil.parseObj(data);
        if (jsonObject.isEmpty())
            return;
        String imageBefore, imageAfter;
        //为所有巡检项生产数据
        for (ItemEnum ti : ItemEnum.values()) {
            //先设置BillItem
            V2ToiletBillBo billBo = new V2ToiletBillBo();
            billBo.setFlowCode(SerialGenerator.flowCode(null, null));
            //根据excel中的 √ × 或 空值 判断状态是什么
            int status = jsonObject.get(ti.attr, Integer.class, true);
            switch (status) {
                case 1:
                    billBo.setStatus(ItemStatusEnum.ERR.intCode);
                    break;
                case 3:
                    billBo.setStatus(ItemStatusEnum.OK.intCode);
                    break;
                default:
                    billBo.setStatus(ItemStatusEnum.NO_DATA.intCode);
                    break;
            }
            billBo.setProjectName(data.getProjectName());
            billBo.setInspectDate(data.getCreateDate());
            billBo.setItem(ti.attr);
            billBo.setModifyCode(ToiletConst.MODIFY_YES);
            billBo.setCommunity(data.getCommunity());
            billBo.setToiletId(data.getId());
            billBo.setItemText(ti.note);
            billBo.setToiletName(data.getToiletName());
            billBo.setCurrUser(data.getCleaner());
            //            billBo.setCurrUser(data.getOwner());
            //增加巡检项 图片ID
            imageBefore = jsonObject.getStr(ti.attr.concat(ToiletConst.EXCEL_IMAGE_BEFORE), "");
            if (StringUtils.isNumeric(imageBefore)) {
                SysOssVo ossVo = iSysOssService.getById(Long.valueOf(imageBefore));
                billBo.setImageBefore(ossVo.getUrl());
            }
            imageAfter = jsonObject.getStr(ti.attr.concat(ToiletConst.EXCEL_IMAGE_AFTER), "");
            if (StringUtils.isNumeric(imageAfter)) {
                SysOssVo ossVo = iSysOssService.getById(Long.valueOf(imageAfter));
                billBo.setImageAfter(ossVo.getUrl());
            }
            billBo.setCreateTime(DateUtil.date());
            //公厕ID加属性ID
            billBo.setId(SecureUtil.md5(data.getId().concat(ti.attr)));
            billBo.setModified(ToiletConst.MODIFY_YES);//可以修改
            bills.add(billBo);
        }


    }

    private String checkData(List<V2ToiletImpDetailVo> data) {
        for(V2ToiletImpDetailVo item:data){
            String imageBefore;
            JSONObject jsonObject = JSONUtil.parseObj(item);
            for (ItemEnum ti : ItemEnum.values()) {
                //先设置BillItem
                //根据excel中的 √ × 或 空值 判断状态是什么
                String attr = ti.attr;
                int status = jsonObject.get(attr, Integer.class, true);

                String _attr = ti.attr.concat(ToiletConst.EXCEL_IMAGE_BEFORE);
                imageBefore = jsonObject.getStr(_attr, "");
                if(status==1 && !StringUtils.isNumeric(imageBefore)){
                    return attr;
                }
            }
        }
        return "";
    }

    public String getAnalysis(MyExcelResult<V2ToiletImpDetailVo> excelResult) {
        //导入**条，成功**条，失败**条
        int count = excelResult.getList().size() / 2;
        int errorCount = excelResult.getErrorList().size() + excelResult.getValidateList().size();
        int successCount = count - errorCount / 2;
        if (count == 0) {
            return "读取失败，未解析到数据";
        } else {
            if (errorCount == 0) {
                return StrUtil.format("导入{}条，成功 {} 条", count, successCount);
            } else if (excelResult.getErrorList().size() == 0) {
                return StrUtil.format("导入{}条，成功 {} 条，失败 {} 条", count, successCount, errorCount);
            } else {
                return StrUtil.format("导入{}条，校功 {} 条，失败 {} 条", count, successCount, errorCount);
            }
        }
    }


}
